<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8" />

    

    

    <title>redis主从模式及哨兵模式 | 郑礼德技术栈</title>
    <meta name="author" content="郑礼德" />
    <meta name="keywords" content="" />
    <meta name="description" content="redis 集群环境主要有3种 ，主从模式，哨兵模式，集群模式，用的较多是集群模式，因为面试中经常问到哨兵模式，所以本文介绍主从模式及哨兵模式的搭建主从模式安装redis安装c++ 编译环境redis 需要gcc-c++ 环境，如果安装过可以忽略yum install -y gcc-c++安装redis1.上传 redis-3.0.0.tar.gz 安装包到服务器中，或者在这里下载2.解压文件tar -xvf redis-3.0.0.tar.gz -C /usr/local..." />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" />

    
    <link rel="alternate" href="/homepage/atom.xml" title="郑礼德技术栈" type="application/atom+xml">
    
    
    <link rel="icon" href="/homepage/images/favicon.ico">
    

    <style type="text/css">
    @font-face {
        font-family: 'icomoon';
        src: url("/homepage/fonts/icomoon.eot?q628ml");
        src: url("/homepage/fonts/icomoon.eot?q628ml#iefix") format('embedded-opentype'),
             url("/homepage/fonts/icomoon.ttf?q628ml") format('truetype'),
             url("/homepage/fonts/icomoon.woff?q628ml") format('woff'),
             url("/homepage/fonts/icomoon.svg?q628ml#icomoon") format('svg');
        font-weight: normal;
        font-style: normal;
    }
    </style>
    
<link rel="stylesheet" href="/homepage/css/style.css">


    <!--[if lt IE 9]>
    <style type="text/css">
    .nav-inner {top:0;}
    .author-meta {position:static;top:0;}
    .search-form {height:36px;}
    </style>
    <script type="text/javascript" src="https://unpkg.com/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
    <![endif]-->
<meta name="generator" content="Hexo 4.2.0"></head>
<body>

    <main class="app">
        <header id="header" class="header clearfix">
    <div id="nav" class="nav">
    <div class="nav-mobile">
        <button id="open-panel" class="open-panel nav-mobile-item"><i class="icon-documents"></i></button>
        <h1 class="nav-mobile-title nav-mobile-item">郑礼德技术栈</h1>
        <button id="open-menus" class="open-panel nav-mobile-item"><i class="icon-library"></i></button>
    </div>

    <nav id="nav-inner" class="nav-inner">
        
            <a class="nav-item" href="/homepage/">
                <span class="nav-text">首页</span>
            </a>
        
            <a class="nav-item" href="/homepage/categories/front-end">
                <span class="nav-text">前端</span>
            </a>
        
            <a class="nav-item" href="/homepage/categories/back-end">
                <span class="nav-text">后端</span>
            </a>
        
            <a class="nav-item" href="/homepage/categories/linux">
                <span class="nav-text">linux部署</span>
            </a>
        
            <a class="nav-item" href="/homepage/tags">
                <span class="nav-text">标签</span>
            </a>
        
            <a class="nav-item" href="/homepage/archives">
                <span class="nav-text">归档</span>
            </a>
        
            <a class="nav-item" href="/homepage/about">
                <span class="nav-text">关于</span>
            </a>
        
    </nav>
</div>

    <aside id="aside" class="aside">
    <div id="aside-mask" class="aside-mask"></div>
    <div id="aside-inner" class="aside-inner">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit"><i class="icon-search-stroke"></i></button><input type="hidden" name="sitesearch" value="http://zhenglide.gitee.io/homepage"></form>

        
        
        
        

        
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#主从模式"><span class="toc-number">1.</span> <span class="toc-text">主从模式</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#安装redis"><span class="toc-number">1.1.</span> <span class="toc-text">安装redis</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#安装c-编译环境"><span class="toc-number">1.1.1.</span> <span class="toc-text">安装c++ 编译环境</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#安装redis-1"><span class="toc-number">1.1.2.</span> <span class="toc-text">安装redis</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#启动redis"><span class="toc-number">1.1.3.</span> <span class="toc-text">启动redis</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#主从模式搭建"><span class="toc-number">1.2.</span> <span class="toc-text">主从模式搭建</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#创建两个slave-目录"><span class="toc-number">1.2.1.</span> <span class="toc-text">创建两个slave 目录</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#复制redis-中文件到目录中"><span class="toc-number">1.2.2.</span> <span class="toc-text">复制redis 中文件到目录中</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#修改从服务配置"><span class="toc-number">1.2.3.</span> <span class="toc-text">修改从服务配置</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#查看主从服务关系"><span class="toc-number">1.2.4.</span> <span class="toc-text">查看主从服务关系</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#验证主从关系"><span class="toc-number">1.3.</span> <span class="toc-text">验证主从关系</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#哨兵模式"><span class="toc-number">2.</span> <span class="toc-text">哨兵模式</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#修改配置文件"><span class="toc-number">2.1.</span> <span class="toc-text">修改配置文件</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#启动哨兵"><span class="toc-number">2.2.</span> <span class="toc-text">启动哨兵</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#验证是否可用"><span class="toc-number">2.3.</span> <span class="toc-text">验证是否可用</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#springboot集成哨兵"><span class="toc-number">2.4.</span> <span class="toc-text">springboot集成哨兵</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#引入依赖"><span class="toc-number">2.4.1.</span> <span class="toc-text">引入依赖</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#application-properties添加配置"><span class="toc-number">2.4.2.</span> <span class="toc-text">application.properties添加配置</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#面试原理分析"><span class="toc-number">2.5.</span> <span class="toc-text">面试原理分析</span></a></li></ol></li></ol>
        
    </div>
</aside>

</header>

        <div id="content" class="content">
            <div id="wrapper" class="wrapper" style="max-width: 800px">
                <article class="article" itemscope itemprop="blogPost">
    
    <header class="article-header">
        
        <h1 itemprop="name">
            redis主从模式及哨兵模式
        </h1>
        
        <div class="article-meta clearfix">
            <a class="article-date" href="http://zhenglide.gitee.io/homepage/2020/10/29/redis%E4%B8%BB%E4%BB%8E%E6%A8%A1%E5%BC%8F%E5%8F%8A%E5%93%A8%E5%85%B5%E6%A8%A1%E5%BC%8F/index.html">
    
    <i class="icon-calendar"></i>
    
    <time datetime="2020-10-29T03:06:16.000Z" itemprop="datePublished">2020-10-29</time>
</a>

            
<div class="article-tag-list">
    <i class="icon-tag"></i>
    <a class="article-tag-link" href="/homepage/tags/linux/" rel="tag">linux</a>, <a class="article-tag-link" href="/homepage/tags/redis/" rel="tag">redis</a>
</div>


        </div>
    </header>
    
    <section class="article-body markdown-body">
        
        <p>redis 集群环境主要有3种 ，主从模式，哨兵模式，集群模式，用的较多是集群模式，因为面试中经常问到哨兵模式，所以本文介绍主从模式及哨兵模式的搭建</p>
<a id="more"></a>



<h2 id="主从模式"><a href="#主从模式" class="headerlink" title="主从模式"></a>主从模式</h2><h3 id="安装redis"><a href="#安装redis" class="headerlink" title="安装redis"></a>安装redis</h3><h4 id="安装c-编译环境"><a href="#安装c-编译环境" class="headerlink" title="安装c++ 编译环境"></a>安装c++ 编译环境</h4><p>redis 需要gcc-c++ 环境，如果安装过可以忽略</p>
<pre><code>yum install -y gcc-c++</code></pre><h4 id="安装redis-1"><a href="#安装redis-1" class="headerlink" title="安装redis"></a>安装redis</h4><p>1.上传 redis-3.0.0.tar.gz 安装包到服务器中，或者<a href="https://redis.io/download" target="_blank" rel="noopener">在这里</a>下载</p>
<p>2.解压文件</p>
<pre><code>tar -xvf redis-3.0.0.tar.gz -C /usr/local/</code></pre><p>3.进入安装目录 /usr/local/redis-3.0.0 安装</p>
<pre><code>make &amp;&amp;  make PREFIX=/opt/deploy/redis install</code></pre><p>4.从redis-3.0.0 拷贝目录文件到redis中并修改配置,如下：</p>
<pre><code class="shell">daemonize yes
pidfile /var/run/redis_6379.pid
port 6379
# bind 127.0.0.1  可选，默认就处理所有请求。
logfile &quot;./redis-6379.log&quot;
dir &quot;./&quot;
#redis配置密码的话，需要以下配置
#masterauth &quot;123456&quot;
#requirepass &quot;123456&quot;
appendonly yes
</code></pre>
<h4 id="启动redis"><a href="#启动redis" class="headerlink" title="启动redis"></a>启动redis</h4><pre><code>./redis-server redis.conf</code></pre><h3 id="主从模式搭建"><a href="#主从模式搭建" class="headerlink" title="主从模式搭建"></a>主从模式搭建</h3><h4 id="创建两个slave-目录"><a href="#创建两个slave-目录" class="headerlink" title="创建两个slave 目录"></a>创建两个slave 目录</h4><pre><code class="shell">mkdir redis637{7,8}</code></pre>
<h4 id="复制redis-中文件到目录中"><a href="#复制redis-中文件到目录中" class="headerlink" title="复制redis 中文件到目录中"></a>复制redis 中文件到目录中</h4><pre><code class="shell">cp -r /opt/deploy/redis/*  /opt/deploy/redis6377 &amp;&amp; cp -r /opt/deploy/redis/*  /opt/deploy/redis6377</code></pre>
<h4 id="修改从服务配置"><a href="#修改从服务配置" class="headerlink" title="修改从服务配置"></a>修改从服务配置</h4><p>主要修改端口号以及加上slaveof [ip] [port] 如下：</p>
<pre><code class="shell">daemonize yes
pidfile /var/run/redis_6378.pid
port 6378
# bind 127.0.0.1  可选，默认就处理所有请求。
logfile &quot;./redis-6378.log&quot;
dir &quot;./&quot;
#指向主服务
slaveof 127.0.0.1 6379
#redis配置密码的话，需要以下配置
#masterauth &quot;123456&quot;
#requirepass &quot;123456&quot;
appendonly yes</code></pre>
<p>然后分别启动两个服务</p>
<pre><code>./redis-server redis.conf</code></pre><h4 id="查看主从服务关系"><a href="#查看主从服务关系" class="headerlink" title="查看主从服务关系"></a>查看主从服务关系</h4><pre><code>./redis-cli -p 6379</code></pre><pre><code class="shell">info replication</code></pre>
<p>然后可以看到以下信息，说明搭建成功</p>
<p>role:master<br>connected_slaves:2<br>slave0:ip=192.168.1.128,port=6378,state=online,offset=990505,lag=1<br>slave1:ip=192.168.1.128,port=6377,state=online,offset=990505,lag=1<br>master_repl_offset:990646<br>repl_backlog_active:1<br>repl_backlog_size:1048576<br>repl_backlog_first_byte_offset:2<br>repl_backlog_histlen:990645</p>
<p>可以看到slave 两个信息</p>
<h3 id="验证主从关系"><a href="#验证主从关系" class="headerlink" title="验证主从关系"></a>验证主从关系</h3><p>在6379 设置一条数据，看是否能在6378 6377 查到</p>
<p>至此，主从就搭建完成，但是这种模式有个弊端就是当主宕机了，必须手动切换到从服务，这个时候就可以用哨兵模式，哨兵模式会监控redis状态，当主redis宕机，哨兵会进行选举，选出从redis 作为主redis,达到自动切换的目的</p>
<h2 id="哨兵模式"><a href="#哨兵模式" class="headerlink" title="哨兵模式"></a>哨兵模式</h2><h3 id="修改配置文件"><a href="#修改配置文件" class="headerlink" title="修改配置文件"></a>修改配置文件</h3><p>1.复制配置文件sentinel.conf到redis目录下</p>
<p>2.修改配置文件，如下：</p>
<pre><code class="shell">daemonize yes
port 26379
#指定工作目录
dir &quot;./&quot;
logfile &quot;./sentinel.log&quot;
#指定别名  主节点地址  端口  哨兵个数（有几个哨兵监控到主节点宕机执行转移）
sentinel monitor mymaster 192.168.1.128 6379 2
#如果哨兵3s内没有收到主节点的心跳，哨兵就认为主节点宕机了，默认是30秒
sentinel down-after-milliseconds mymaster 3000
#选举出新的主节点之后，可以同时连接从节点的个数
sentinel failover-timeout mymaster 10000
#如果10秒后,master仍没活过来，则启动failover,默认180s
sentinel config-epoch mymaster 0
#配置连接redis主节点密码
#sentinel auth-pass mymaster 123456</code></pre>
<p>3.复制多两份到6377 6378</p>
<pre><code class="sh">cp -r sentinel.conf ../redis6377/ &amp;&amp; cp -r sentinel.conf ../redis6378/</code></pre>
<p>4.修改另外两份端口信息</p>
<h3 id="启动哨兵"><a href="#启动哨兵" class="headerlink" title="启动哨兵"></a>启动哨兵</h3><p>使用以下命令启动三个服务</p>
<pre><code class="sh">./redis-sentinel sentinel.conf</code></pre>
<h3 id="验证是否可用"><a href="#验证是否可用" class="headerlink" title="验证是否可用"></a>验证是否可用</h3><p>手动关闭主节点 </p>
<pre><code class="shell">kill -9 [pid]</code></pre>
<p>查看哨兵日志</p>
<pre><code>14993:X 21 Oct 10:21:46.472 # +sdown master mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:46.525 # +odown master mymaster 192.168.1.128 6379 #quorum 2/2
14993:X 21 Oct 10:21:46.525 # +new-epoch 1
14993:X 21 Oct 10:21:46.525 # +try-failover master mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:46.527 # +vote-for-leader a07954b09d2820bf695fc4fdf61bb3f78f89c0b8 1
14993:X 21 Oct 10:21:46.529 # 192.168.1.128:26379 voted for a07954b09d2820bf695fc4fdf61bb3f78f89c0b8 1
14993:X 21 Oct 10:21:46.529 # 192.168.1.128:26377 voted for a07954b09d2820bf695fc4fdf61bb3f78f89c0b8 1
14993:X 21 Oct 10:21:46.580 # +elected-leader master mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:46.580 # +failover-state-select-slave master mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:46.636 # +selected-slave slave 192.168.1.128:6378 192.168.1.128 6378 @ mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:46.636 * +failover-state-send-slaveof-noone slave 192.168.1.128:6378 192.168.1.128 6378 @ mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:46.695 * +failover-state-wait-promotion slave 192.168.1.128:6378 192.168.1.128 6378 @ mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:47.567 # +promoted-slave slave 192.168.1.128:6378 192.168.1.128 6378 @ mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:47.567 # +failover-state-reconf-slaves master mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:47.629 * +slave-reconf-sent slave 192.168.1.128:6377 192.168.1.128 6377 @ mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:48.649 * +slave-reconf-inprog slave 192.168.1.128:6377 192.168.1.128 6377 @ mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:48.649 * +slave-reconf-done slave 192.168.1.128:6377 192.168.1.128 6377 @ mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:48.714 # -odown master mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:48.714 # +failover-end master mymaster 192.168.1.128 6379
14993:X 21 Oct 10:21:48.714 # +switch-master mymaster 192.168.1.128 6379 192.168.1.128 6378
14993:X 21 Oct 10:21:48.715 * +slave slave 192.168.1.128:6377 192.168.1.128 6377 @ mymaster 192.168.1.128 6378
14993:X 21 Oct 10:21:48.716 * +slave slave 192.168.1.128:6379 192.168.1.128 6379 @ mymaster 192.168.1.128 6378
14993:X 21 Oct 10:21:51.760 # +sdown slave 192.168.1.128:6379 192.168.1.128 6379 @ mymaster 192.168.1.128 6378</code></pre><p>可以看到哨兵经过选举后切换到6378 的节点作为主节点</p>
<h3 id="springboot集成哨兵"><a href="#springboot集成哨兵" class="headerlink" title="springboot集成哨兵"></a>springboot集成哨兵</h3><h4 id="引入依赖"><a href="#引入依赖" class="headerlink" title="引入依赖"></a>引入依赖</h4><pre><code class="xml"> &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-data-redis&lt;/artifactId&gt;
        &lt;/dependency&gt;</code></pre>
<h4 id="application-properties添加配置"><a href="#application-properties添加配置" class="headerlink" title="application.properties添加配置"></a>application.properties添加配置</h4><pre><code class="properties">spring.redis.sentinel.master=mymaster
spring.redis.sentinel.nodes=192.168.1.128:26379,192.168.1.128:26378,192.168.1.128:26377</code></pre>
<h3 id="面试原理分析"><a href="#面试原理分析" class="headerlink" title="面试原理分析"></a>面试原理分析</h3><p>1哨兵集群会对redis 集群进行监控，并发出ping心跳检测连接，如果其中一个sentinel检测主节点下线后，此时认为节点为主观下线</p>
<p>2.此时会在指定时间 范围内如果其他sentinel 确认master 下线的数量到达的时候，会认为主节点客观下线</p>
<p>3.哨兵将会进行选举策略</p>
<p>a)每个在线的哨兵节点都可以成为领导者，当它确认（比如哨兵3）主节点下线时，会向其它哨兵发is-master-down-by-addr命令，征求判断并要求将自己设置为领导者，由领导者处理故障转移；<br>b)当其它哨兵收到此命令时，可以同意或者拒绝它成为领导者；<br>c)如果哨兵3发现自己在选举的票数大于等于num(sentinels)/2+1时，将成为领导者，如果没有超过，继续选举…………</p>
<p>4.选择新的主节点，切换成功</p>

        
    </section>
</article>



<a id="pagenext" href="/homepage/2020/10/20/%E4%BD%BF%E7%94%A8mycat%E6%90%AD%E5%BB%BA%E6%95%B0%E6%8D%AE%E5%BA%93%E9%9B%86%E7%BE%A4%E8%AF%BB%E5%86%99%E5%88%86%E7%A6%BB/" class="article-next" title="使用mycat搭建数据库集群读写分离"><i class="icon-arrow-right"></i></a>


<a id="pageprev" href="/homepage/2020/10/29/redisson%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/" class="article-prev" title="redisson分布式锁"><i class="icon-arrow-left"></i></a>




            </div>
        </div>
        <footer class="footer">
    Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>, Theme by <a href="https://github.com/sanonz/hexo-theme-concise" target="_blank">Concise</a>

    
    <script>
        var _hmt = _hmt || [];
        (function () {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?b13bb4c2ef8300062aab9732bd22eae0";
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(hm, s);
        })();
    </script>
    
</footer>

    </main>

    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.9.0/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
        var nodes = {
            nav: $('#nav'),
            aside: $('#aside'),
            asideInner: $('#aside-inner'),
            navInner: $('#nav-inner')
        };

        var doing = false;
        nodes.asideInner.on('webkitAnimationEnd mozAnimationEnd oAnimationEnd oanimationend animationend', function() {
            if (nodes.aside.hasClass('mobile-open')) {
                nodes.aside.removeClass('mobile-open');
            } else {
                nodes.aside.removeClass('mobile-close panel-show');
            }
            doing = false;
        });
        $('#open-panel, #aside-mask').on('click', function() {
            if (doing) {
                return;
            }

            if (nodes.aside.hasClass('panel-show')) {
                nodes.aside.addClass('mobile-close');
            } else {
                nodes.aside.addClass('mobile-open panel-show');
            }
        });
        $('#open-menus').on('click', function() {
            nodes.navInner.slideToggle();
        });

        if (window.innerWidth <= 960) {
            setTimeout(function() {
                nodes.navInner.slideUp();
            }, 3000);
        }
    });
    </script>
    
        
<script src="/homepage/js/scrollspy.min.js"></script>

        <script type="text/javascript">
        $(document.body).scrollspy({target: '#aside-inner'});

        $(window).on('resize', function() {
            var hw = $('#header').width();
            var ww = $('#wrapper').width();
            var space = ($(this).width() - hw - ww) / 2 / 2;

            var pageprev = $('#pageprev');
            var pagenext = $('#pagenext');
            var avg = (pageprev.width() + pagenext.width()) / 2

            if(space > avg) {
                var len = space - avg / 2;
                var styles = {position: 'fixed', top: '50%', marginTop: - (pageprev.width() + pagenext.width()) / 4}
                pageprev.css($.extend({left: hw + len}, styles));
                pagenext.css($.extend({right: len}, styles));
            } else {
                pageprev.removeAttr('style');
                pagenext.removeAttr('style');
            }
        }).trigger('resize');
        </script>
    

</body>
</html>
